package model;
import java.io.*;

import utils.Date;
import utils.TextUtils;

public class TableInformationReader {
	
	public static int MAX_ENTITIES_PER_CELL = 10;
	

	public static TableInformation readTableInformation(String entity_filename,
														String type_filename,
														String fact_filename,
														String predicate_info_filename,
														String predicate_to_mediator_filename,
														int max_entities_per_cell) throws IOException {
		System.out.print("Reading in cell entities...");
		System.out.println(entity_filename);
		TableInformation table_info = readInCellEntities(entity_filename, max_entities_per_cell);
		if (table_info == null) {
			System.out.println();
			System.out.println("Error.");
			return null;
		}
		System.out.println("Done.");
		
		System.out.print("Reading in entities to their types...");
		boolean completed = readInEntitiesToTypes(table_info, type_filename);
		if (!completed) {
			System.out.println();
			System.out.println("Error.");
			return null;
		}
		System.out.println("Done.");
		
		System.out.print("Reading in predicate information...");
		completed = readInPredicateInformation(table_info, predicate_info_filename);
		if (!completed) {
			System.out.println();
			System.out.println("Error.");
			return null;
		}
		System.out.println("Done.");
		
		System.out.print("Reading in relations to mediators...");
		completed = readInPredicateToMediators(table_info, predicate_to_mediator_filename);
		if (!completed) {
			System.out.println();
			System.out.println("Error.");
			return null;
		}
		System.out.println("Done.");
		
		System.out.print("Reading in known facts...");
		completed = readInKnownFacts(table_info, fact_filename);
		if (!completed) {
			System.out.println();
			System.out.println("Error.");
			return null;
		}
		System.out.println("Done.");
		return table_info;
	}
	
	private static boolean readInPredicateToMediators(
			TableInformation table_info, String predicate_to_mediator_filename) {
		try {
			BufferedReader reader = new BufferedReader(new FileReader(predicate_to_mediator_filename));
			String line;
			while ((line = reader.readLine()) != null) {
				String[] split = line.split("\t");
				Integer predicate_id = table_info.getIdForString(split[0]);
				if (predicate_id == null)
					continue;
				Integer cvt_id = table_info.getIdForString(split[1]);
				table_info.identifyPredicateAsExpectedCvt(predicate_id);
				table_info.identifyTypeAsCvt(cvt_id);
				PredicateInfo p_info = table_info.getPredicateInfo(predicate_id);
				if (p_info != null)
					p_info.setExpectsCvt(true);
			}
			reader.close();
			return true;
		} catch (IOException x) {
			x.printStackTrace();
			return false;
		}
	}

	private static boolean readInKnownFacts(TableInformation table_info,
			String fact_filename) {
		try {
			BufferedReader reader = new BufferedReader(new FileReader(fact_filename));
			String line;
			while ((line = reader.readLine()) != null) {
				String[] fact = line.split("\t");
				if (fact.length != 3)
					continue;
				if (fact[1].contains("location"))
					continue;
				table_info.addFact(fact[0], fact[1], fact[2]);
			}
			reader.close();
			return true;
		} catch (IOException x) {
			x.printStackTrace();
			return false;
		}
	}

	private static boolean readInPredicateInformation(
			TableInformation table_info, String predicate_info_filename) {
		try {
			BufferedReader reader = new BufferedReader(new FileReader(predicate_info_filename));
			String line;
			while ((line = reader.readLine()) != null) {
				String[] split = line.split("\t");
				if (split.length < 6) 
					continue;
				Integer domain_id = table_info.getIdForString(split[1]);
				if (split[0].equals("/tv/tv_series_episode/series")) {
					System.out.println("QQQ " + domain_id);
				}
				if (domain_id == null)
					continue;
				Integer range_id = table_info.getIdForString(split[2]);
				if (split[0].equals("/tv/tv_series_episode/series")) {
					System.out.println("QQQQ " + range_id + " " + split[2]);
				}
				if (range_id == null)
					continue;
				Integer predicate_id = table_info.getOrAddIdForString(split[0]);
				Integer reverse_id = null;
				if (!split[3].equals(""))
					reverse_id = table_info.getOrAddIdForString(split[3]);
				else if (!split[4].equals(""))
					reverse_id = table_info.getOrAddIdForString(split[4]);
				boolean is_functional = false;
				if (split[5].equals("True"))
					is_functional = true;
				PredicateInfo p_info = table_info.getPredicateInfo(predicate_id);
				if (p_info == null) {
					p_info = new PredicateInfo(predicate_id, domain_id, range_id,
															 reverse_id, is_functional);
					table_info.addPredicateInfo(p_info);
				} else {
					p_info.setIsFunctional(is_functional);
				}
				
				if (reverse_id != null) {
					PredicateInfo reverse_p_info = table_info.getPredicateInfo(reverse_id);
					if (reverse_p_info == null) {
						reverse_p_info = new PredicateInfo(reverse_id, range_id, domain_id,
														   predicate_id, false);
						table_info.addPredicateInfo(reverse_p_info);
					}
				}
			}
			reader.close();
			return true;
		} catch (IOException x) {
			x.printStackTrace();
			return false;
		}
	}

	public static TableInformation readTableInformation(String entity_filename,
														String type_filename,
														String fact_filename,
														String predicate_info_filename,
														String predicate_to_mediator_filename) throws IOException {
		return readTableInformation(entity_filename, type_filename, fact_filename,
									predicate_info_filename, predicate_to_mediator_filename,
									MAX_ENTITIES_PER_CELL);
	}
	
	private static boolean readInEntitiesToTypes(TableInformation table_info, String type_filename) {
		try {
			BufferedReader reader = new BufferedReader(new FileReader(type_filename));
			System.out.println(type_filename);
			String line;
			while ((line = reader.readLine()) != null) {
				String[] split = line.split("\t");
				if (line.contains("location"))
					continue;
				table_info.addTypesForEntity(split[0], split[1].split(","));
			}
			reader.close();
			return true;
		} catch (IOException x) {
			x.printStackTrace();
			return false;
		}
	}
	
	private static TableInformation readInCellEntities(String entity_filename, int max_entities_per_cell) throws IOException {
		BufferedReader reader = new BufferedReader(new FileReader(entity_filename));
	    String line = null;
	    line = reader.readLine();
	    String[] table_size = line.split("\t");
	    int num_rows = Integer.parseInt(table_size[0]);
//	    num_rows = 10;
	    int num_cols = Integer.parseInt(table_size[1]);
	    TableInformation table_info = new TableInformation(num_rows, num_cols);
	    
	    while ((line = reader.readLine()) != null) {
	        String[] split = line.split("\t");
	        int row = Integer.parseInt(split[0]);
//	        if (row > 9)
//	        	continue;
//	        if (row == 14) {
//	        	row = 0;
//	        } else {
//	        	row = 1;
//	        }
	        int col = Integer.parseInt(split[1]);
	        System.out.println(line);
	        String text = null;
	        if (split.length == 2) {
	        	text = "";
	        } else {
	        	text = split[2];
	        }
	        if (split.length == 4) {
	        	String sem = split[3];
	        	String[] cell_entities = sem.split(",");
	        	if (max_entities_per_cell != 0 &&
	        		cell_entities.length < max_entities_per_cell) {
	        		Integer[] cell_entity_ids = new Integer[cell_entities.length];
	        		for (int e = 0; e < cell_entities.length; e++) {
	        			if (!TextUtils.isMid(cell_entities[e])) {
	        				table_info.setLeafColumn(col);
	        				Double num = TextUtils.parseNumericString(cell_entities[e]);
	        				if (num == null) {
	        					Date date = Date.parseTextDate(cell_entities[e]);
	        					if (date != null) {
	        						cell_entities[e] = date.toString();
	        					}
	        				} else {
	        					Integer integer = TextUtils.parseIntegerString(cell_entities[e]);
	        					if (integer != null) {
	        						cell_entities[e] = Integer.toString(integer);
	        					} else {
	        						cell_entities[e] = Double.toString(num);
	        					}
	        				}
	        			}
	        			if (row == 1 && col == 5) {
	        				System.out.println(cell_entities[e]);
	        			}
	        			cell_entity_ids[e] = table_info.getOrAddIdForString(cell_entities[e]);
	        			table_info.identifyEntityAsVisible(cell_entity_ids[e]);
	        		}
	        		table_info.setCellEntities(row, col, cell_entity_ids);
	        	} else {
	        		Integer[] short_cell_entities = new Integer[max_entities_per_cell];
	        		for (int e = 0; e < max_entities_per_cell; e++) {
	        			if (!TextUtils.isMid(cell_entities[e])) {
	        				table_info.setLeafColumn(col);
	        				Double num = TextUtils.parseNumericString(cell_entities[e]);
	        				if (num == null) {
	        					Date date = Date.parseKBDate(cell_entities[e]);
	        					if (date != null) {
	        						cell_entities[e] = date.toString();
	        					}
	        				} else {
	        					cell_entities[e] = Double.toString(num);
	        				}
	        			}
	        			Integer ent_id = table_info.getOrAddIdForString(cell_entities[e]);
	        			short_cell_entities[e] = ent_id;
	        			table_info.identifyEntityAsVisible(ent_id);
	        		}
	        		table_info.setCellEntities(row, col, short_cell_entities);
	        	}
	        } else {
	        	if (text.equals("")) {
	        		continue;
	        	}
	        	Integer ent_id = table_info.getOrAddIdForString(text);
	        	Integer[] short_cell_entities = new Integer[] { ent_id };
	        	table_info.setCellEntities(row, col, short_cell_entities);
	        }
	        table_info.setCellText(row, col, text);
	    }
	    reader.close();
	    return table_info;
	}
}
